<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>07.现存架构的问题</title>
  </head>

  <body>
    <div id="app">
      <p v-text="name"></p>
      <p v-text="name"></p>
      <span v-text="age"></span>
    </div>

    <script>
      let data = {
        name: "柴柴老师",
        age: 29,
      };
      // 把data中的属性变成响应式的
      Object.keys(data).forEach((key) => {
        defineReactive(data, key, data[key]);
      });
      function defineReactive(data, key, value) {
        // 进行转换操作
        Object.defineProperty(data, key, {
          get() {
            return value;
          },
          set(newValue) {
            // set函数的执行 不会自动判断俩次修改的值是否相等
            // 显然如果相等 不应该执行变化的逻辑
            if (newValue === value) {
              return;
            }

            value = newValue;
            // 这里我们把最新的值 反映到视图中  这里是关键的位置
            // 核心：操作dom  就是通过操作dom api 把最新的值设置上去
            compile();
          },
        });
      }
      // 1.通过标识查找把数据放到对应的dom上显示出来
      function compile() {
        let app = document.getElementById("app");
        // 拿到所有节点
        const childNodes = app.childNodes; // 所有类型的节点包括文本节点和标签节点
        childNodes.forEach((node) => {
          if (node.nodeType === 1) {
            const attrs = node.attributes;
            Array.from(attrs).forEach((attr) => {
              const nodeName = attr.nodeName;
              const nodeValue = attr.nodeValue;
              // 实现v-text
              if (nodeName === "v-text") {
                console.log(`当前您修改了属性${nodeValue}`);
                node.innerText = data[nodeValue];
              }
              // 实现v-model
              if (nodeName === "v-model") {
                // 调用dom操作给input标签绑定数据
                node.value = data[nodeValue];
                // 监听input事件 在事件回调中 拿到最新的输入值 赋值给绑定的属性
                node.addEventListener("input", (e) => {
                  let newValue = e.target.value;
                  // 反向赋值
                  data[nodeValue] = newValue;
                });
              }
            });
          }
        });
      }
      compile();
    </script>
    <!-- 
      存在的问题：更新太过粗暴
      不管你修改了哪个属性,其它属性也会一起跟着进行更新 哪怕你根本就没有动他
      只修改了name的时候 正常逻辑  应该只有name相关的更新操作才进行 而不是粗暴的  把所有的都更新一遍

      期望：
        哪个属性进行了实质性的修改 哪个属性对应的‘编译’部分才得到执行，这个更新优 化
        我们称之为‘精准更新’
    -->
  </body>
</html>
